/**
  需求：实现一个图片懒加载指令，只加载浏览器可见区域的图片。
  
  思路：
    图片懒加载的原理主要是判断当前图片是否到了可视区域这一核心逻辑实现的
    拿到所有的图片 Dom ，遍历每个图片判断当前图片是否到了可视区范围内
    如果到了就设置图片的 src 属性，否则显示默认图片

    图片懒加载有两种方式可以实现，一是绑定 srcoll 事件进行监听，二是使用 
  IntersectionObserver 判断图片是否到了可视区域，但是有浏览器兼容性问题。
    下面封装一个懒加载指令兼容两种方法，判断浏览器是否支持 IntersectionO
  bserver API，如果支持就使用 IntersectionObserver 实现懒加载，否则则
  使用 srcoll 事件监听 + 节流的方法实现
 */
import { ObjectDirective } from 'vue';

// 初始化
function init(el: any, val: string, def: string) {
  el.setAttribute('data-src', val)
  el.setAttribute('src', def)
}
// 利用IntersectionObserver监听el
function observe(el: any) {
  var io = new IntersectionObserver((entries) => {
    const realSrc = el.dataset.src
    if (entries[0].isIntersecting) {
      if (realSrc) {
        el.src = realSrc
        el.removeAttribute('data-src')
      }
    }
  })
  io.observe(el)
}

// 监听scroll事件
// 在监听scroll部分，对每个懒加载元素都进行了监听，如果页面图片特别多的情况下，性能消耗较大，可以优化为全局只监听一次scroll事件，然后遍历具有data-src属性的节点
function listenerScroll(el: any) {
  const handler = throttle(load, 300)
  load(el)
  window.addEventListener('scroll', () => {
    handler(el)
  })
}
// 加载真实图片
function load(el: any) {
  const windowHeight = document.documentElement.clientHeight
  const elTop = el.getBoundingClientRect().top
  const elBtm = el.getBoundingClientRect().bottom
  const realSrc = el.dataset.src
  if (elTop - windowHeight < 0 && elBtm > 0) {
    if (realSrc) {
      el.src = realSrc
      el.removeAttribute('data-src')
    }
  }
}
// 节流
function throttle(fn: Function, delay: number) {
  let timer: any;
  let prevTime: any;
  return function (...args: any[]) {
    const currTime = Date.now()
    // @ts-ignore
    const context = this;
    if (!prevTime) prevTime = currTime
    clearTimeout(timer)

    if (currTime - prevTime > delay) {
      prevTime = currTime
      fn.apply(context, args)
      clearTimeout(timer)
      return
    }

    timer = setTimeout(function () {
      prevTime = Date.now()
      timer = null
      fn.apply(context, args)
    }, delay)
  }
}
const lazyLoad: ObjectDirective<any, string> = {
  created(el, binding) {
    debugger
    init(el, binding.value, "https://cube.elemecdn.com/e/fd/0fc7d20532fdaf769a25683617711png.png")
  },
  mounted(el, binding) {
    debugger
    if (IntersectionObserver) {
      observe(el)
    } else {
      listenerScroll(el)
    }
  }
}

export default lazyLoad;